/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package analiseSintatica.Regras.Expressoes;

import analiseSintatica.Regras.Declaracoes.RegraAtribuicaoVar;
import analiseSintatica.Regras.Funcao.RegraArgsChamada;
import analiseSintatica.Regras.*;
import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSintatica.ErroSintaticoException;
import analiseSintatica.estruturadados.NoArvore;
import java.util.LinkedList;

/**
 *
 * @author linton
 */
public class RegraExpressao extends Regra {

    protected static Regra instancia;


    RegraLogicaE Regralogica_e = RegraLogicaE.getInstance();
    protected String estrutura = "<logica_e> {|| <logica_e>}";



    /**
     * Construtor privado necessario ao singleton
     */
    private RegraExpressao() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraExpressao getInstance() {
        if (instancia == null) {
            instancia = new RegraExpressao();
        }
        return (RegraExpressao) instancia;
    }
    

    @Override
    public NoArvore analisar(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {
        NoArvore noExpressao = new NoArvore("<expressao>", false);


        noExpressao.adicionaFilho(reconhecerLogica_e(listaTokens));

        while (listaTokens.getFirst().getToken().equals("operador_logico")) {
            noExpressao.adicionaFilho(reconhecerOu(listaTokens));
            noExpressao.adicionaFilho(reconhecerLogica_e(listaTokens));
        }
        return noExpressao;
    }

    public NoArvore reconhecerLogica_e(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {
        LinkToken token = listaTokens.getFirst();

        if (Regralogica_e.getPrimeiro().contains(token.getToken())) {
            return Regralogica_e.analisar(listaTokens);
        }
        ErroSintaticoException erro = new ErroSintaticoException();
        erro.addErros("Erro na logica e", estrutura, listaTokens.getFirst().getLinha());
        throw erro;

    }

    public NoArvore reconhecerOu(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {
        LinkToken token = listaTokens.removeFirst();

        if (token.getLexema().equals("||")) {
            return new NoArvore("operador_logico", true);
        }
        ErroSintaticoException erro = new ErroSintaticoException();
        erro.addErros("Falta operador logico", estrutura, token.getLinha());
        throw erro;
    }

    
    

    @Override
    protected void setPrimeiro() {
        // P<expressao> = P<cast>
        primeiro.add("(");
        primeiro.add("{");
        primeiro.add("identificador");
        primeiro.add("numeroInteiro");
        primeiro.add("numeroFlutuante");
        primeiro.add("charconst");
        primeiro.add("++");
        primeiro.add("--");
        primeiro.add("&");
        primeiro.add("*");
    }

    @Override
    protected void setSeguinte() {
        /* S<expressao> = {";", ",", "}" ")"} U S<args_chamada> U S<atribuicao_var> U S<atribuicao>
        ->  S<expressao> = {";", ",", "}" ")"}*/
        this.seguinte.add(";");
        this.seguinte.add(",");
        this.seguinte.add("}");
        this.seguinte.add(")");
        
    }
}
